package com.hzy.fivepalace.db.service;

import com.hzy.fivepalace.common.util.ResponseUtil;
import com.hzy.fivepalace.db.dao.DtsNoDeliveryRegionMapper;
import com.hzy.fivepalace.db.dao.ex.CommonMapperEx;
import com.hzy.fivepalace.db.domain.DtsNoDeliveryRegion;
import com.hzy.fivepalace.db.domain.DtsNoDeliveryRegionExample;
import com.hzy.fivepalace.db.domain.DtsSystem;
import org.apache.commons.lang3.StringUtils;
import org.redisson.Redisson;

import org.redisson.api.RLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;


/**
 * 物流服务
 */
@Service
public class DtsLogisticsService {

    private static final Logger logger = LoggerFactory.getLogger(DtsLogisticsService.class);

    @Autowired
    private DtsSystemConfigService systemConfigService;

    @Resource
    private DtsNoDeliveryRegionMapper noDeliveryRegionMapper;

    @Resource
    private Redisson redisson;

    @Resource
    private CommonMapperEx commonMapperEx;

    private final static ArrayBlockingQueue<Runnable> WORK_QUEUE = new ArrayBlockingQueue<>(9);

    private final static RejectedExecutionHandler HANDLER = new ThreadPoolExecutor.CallerRunsPolicy();

    private static ThreadPoolExecutor executorService = new ThreadPoolExecutor(16, 16, 1000, TimeUnit.MILLISECONDS,
            WORK_QUEUE, HANDLER);


    /**
     * 获取物流说明
     *
     * @return
     */
    public String getLogisticsInstructions() {
        String instructions = "/";
        DtsSystem dtsSystem = systemConfigService.selectByKey("dts.logistics.instructions");
        if (null != dtsSystem && !StringUtils.isBlank(dtsSystem.getKeyValue())) {
            instructions = dtsSystem.getKeyValue();
        }
        return instructions;
    }

    /**
     * 修改物流说明
     * @param content
     * @return
     */
    public Object updLogisticsInstructions(String content) {
        RLock lock = redisson.getLock("admin_upd_logistics_instructions");
        if (lock.isLocked()) {
            return ResponseUtil.frequent("其他管理人员操作中,请稍后再试");
        }
        lock.lock(30, TimeUnit.SECONDS);
        if (StringUtils.isBlank(content)) {
            lock.unlock();
            return ResponseUtil.fail("内容不能为空");
        }
        if (content.length() > 300) {
            lock.unlock();
            return ResponseUtil.fail("内容最多300个字");
        }

        DtsSystem dtsSystem = systemConfigService.selectByKey("dts.logistics.instructions");
        if(null==dtsSystem){
            dtsSystem=new DtsSystem();
            dtsSystem.setDeleted(false);
            dtsSystem.setKeyValue(content);
            dtsSystem.setAddTime(LocalDateTime.now());
            dtsSystem.setUpdateTime(LocalDateTime.now());
            dtsSystem.setKeyName("dts.logistics.instructions");
            systemConfigService.insertSelective(dtsSystem);
        }else{
            dtsSystem.setUpdateTime(LocalDateTime.now());
            dtsSystem.setKeyValue(content);
            systemConfigService.updateByPrimaryKeySelective(dtsSystem);
        }
        lock.unlock();
        return ResponseUtil.ok("修改成功",null);
    }


    /**
     * 获取不发货地区
     * @param name
     * @return
     */
    public List<DtsNoDeliveryRegion> getNoDeliveryRegionList(String name) {
        DtsNoDeliveryRegionExample example = new DtsNoDeliveryRegionExample();
        example.setOrderByClause("create_time desc");
        if(!StringUtils.isBlank(name)){
            example.createCriteria().andNameLike("%"+name+"%");
        }
        List<DtsNoDeliveryRegion> list = noDeliveryRegionMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(list)) {
            list = new ArrayList<>();
        }
        return list;
    }

    public Object addNoDeliveryRegion(DtsNoDeliveryRegion region,Integer adminId) {
        RLock lock = redisson.getLock("admin_add_noDeliveryRegion_"+adminId);
        if (lock.isLocked()) {
            return ResponseUtil.frequent();
        }
        lock.lock(30, TimeUnit.SECONDS);


        if(null==region.getRegionId()||region.getRegionId().intValue()<1){
            lock.unlock();
            return ResponseUtil.fail("请选择城市");
        }
        if(StringUtils.isBlank(region.getName())){
            lock.unlock();
            return ResponseUtil.fail("参数【name】为空");
        }
        region.setCreateTime(LocalDateTime.now());
        noDeliveryRegionMapper.insertSelective(region);
        lock.unlock();
        return ResponseUtil.ok("新增成功",null);
    }

    /**
     * 删除不发货地区
     * @param id
     * @return
     */
    public Object delNoDeliveryRegionListByThread(Integer id) {
        RLock lock = redisson.getLock("admin_del_noDeliveryRegion_"+id);
        if (lock.isLocked()) {
            return ResponseUtil.frequent("其他管理人员操作中,请稍后再试");
        }
        lock.lock(30, TimeUnit.SECONDS);
        noDeliveryRegionMapper.deleteByPrimaryKey(id);
        lock.unlock();
        return ResponseUtil.ok("删除成功",null);
    }


    /**
     * 获取不发货地区(开启线程)
     * @param name
     * @return
     */
    public Object getNoDeliveryRegionListByThread(String name) {
        //获取不发货地区
        Callable<List<DtsNoDeliveryRegion>> noDeliveryRegionCallable = () ->getNoDeliveryRegionList(name);
        FutureTask<List<DtsNoDeliveryRegion>> noDeliveryRegionListTask = new FutureTask<>(noDeliveryRegionCallable);
        executorService.submit(noDeliveryRegionListTask);
        try {
            return noDeliveryRegionListTask.get();
        } catch (Exception e) {
            logger.error("获取不发货地区出错,msg:{}",e.getMessage());
            return ResponseUtil.fail("获取出错");
        }
    }

    /**
     * 根据省份id和市id判断是否可以发货
     *
     * @param provinceId
     * @param cityId
     * @return
     */
    public boolean isDeliveryByProvinceIdAndCityId(Integer provinceId, Integer cityId) {

        return commonMapperEx.isDeliveryByProvinceIdAndCityId(provinceId, cityId);
    }


}
